<?php
// +----------------------------------------------------------------------
// | QSCMS
// +----------------------------------------------------------------------
// | Copyright (c)  2025 https://www.qqss.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed QSCMS is not free software, commercial use must purchase official license from official website to avoid unnecessary legal disputes.
// +----------------------------------------------------------------------
// | Author: Contract 990504246@qq.com
// +----------------------------------------------------------------------

namespace app\common\model;

use think\Model;

class User extends Model
{
    protected $autoWriteTimestamp = true;

    protected $type = [
        'money' => 'float',
    ];
    public function orders($search = [])
    {
        $query = $this->hasManyThrough(
            'GoodsOrder',
            'UserOrder',
            'user_id', // PersonalOrder表中的外键
            'id', // Order表中的主键
            'id', // PersonalUser表中的主键
            'order_id' // PersonalOrder表中与Order表关联的键
        );
        foreach ($search as $field => $value) {
            if ($value) {
                $query->whereHas('Order', function ($q) use ($field, $value) {
                    $q->withSearch($field, $value);
                });
            }
        }

        return $query;
    }

    // 搜索器开始
    public function searchFieldAttr($query, $value, $data)
    {
        if (empty($data['keyword'])) {
            return;
        }
        if ($value == 'username') {
            $query->where('username', 'like', '%' . $data['keyword'] . '%');
        }

        if ($value == 'id') {
            $query->where('id', $data['keyword']);
        }
        if ($value == 'mobile') {
            $query->where('mobile', $data['keyword']);
        }

        if ($value == 'qq') {
            $query->where('qq', $data['keyword']);
        }
    }
    public function searchKeywordAttr($query, $value, $data)
    {
    }

    public function searchIdAttr($query, $value, $data)
    {
        $query->where('id', $value);
    }

    public function searchStatusAttr($query, $value, $data)
    {
        $query->where('status', $value);
    }

    public function searchIsFreezeAttr($query, $value, $data)
    {
        $query->where('is_freeze', $value);
    }

    public function searchDateRangeAttr($query, $value, $data)
    {
        if (empty($value) || empty($value[0]) || empty($value[1])) {
            return;
        }
        if ($value[0] == $value[1]) {
            $query->whereTime('create_time', strtotime($value[0]));
            return;
        }
        $query->whereBetweenTime('create_time', strtotime($value[0]), strtotime($value[1]));
    }
    // 搜索器结束

    public function getAvatarAttr($value, $data)
    {
        // 如果为空，则返回默认头像
        if (empty($value)) {
            return conf('site_domain') . '/static/common/images/noavatar.png';
        }
        // 如果以http开头，则返回原值
        if (strpos($value, 'http') === 0) {
            return $value;
        }
        return conf('site_domain') . $value;
    }

    /**
     * 获取用户收藏的商品
     */
    public function favoritedGoods()
    {
        return $this->hasManyThrough(
            'Goods',
            'UserFavorite',
            'user_id', // UserFavorite表中的外键
            'id', // Goods表中的主键
            'id', // User表中的主键
            'relation_id' // UserFavorite表中与Goods表关联的键
        )->where('user_favorite.type', 1);
    }

    /**
     * 获取用户收藏记录
     */
    public function favorites()
    {
        return $this->hasMany('UserFavorite', 'user_id');
    }

    protected function getOptions(): array
    {
        return [
            'autoWriteTimestamp' => true,
            'jsonAssoc'          => true,
        ];
    }

    /**
     * 关联会员等级
     */
    public function level()
    {
        return $this->belongsTo('UserLevel', 'level_id');
    }

    /**
     * 关联VIP记录
     */
    public function vipRecords()
    {
        return $this->hasMany('UserVipRecord', 'user_id');
    }

    /**
     * 获取当前有效的VIP记录
     */
    public function currentVip()
    {
        return $this->vipRecords()
            ->where('status', 1)
            ->where('end_time', '>', date('Y-m-d H:i:s'))
            ->order('end_time', 'desc')
            ->find();
    }

    /**
     * 判断用户是否为VIP
     * @return bool
     */
    public function isVip()
    {
        return !empty($this->currentVip()) && (!empty($this->vip_expire_time) && $this->vip_expire_time > date('Y-m-d H:i:s'));
    }

    /**
     * 获取用户VIP等级ID
     * @return int|null
     */
    public function getVipId()
    {
        $vipRecord = $this->currentVip();
        return $vipRecord ? $vipRecord->vip_id : null;
    }

    /**
     * 获取用户VIP信息
     * @return array|null
     */
    public function getVipInfo()
    {
        $vipRecord = $this->currentVip();
        if (!$vipRecord) {
            return null;
        }

        $vip = UserVip::find($vipRecord->vip_id);
        if (!$vip) {
            return null;
        }

        // 报错兼容 不在修复 或可考虑 $vip->getData('name'),
        return [
            'id'          => $vip->id,
            'name'        => $vip->name,
            'icon'        => $vip->icon,
            'expire_time' => $vipRecord->end_time,
        ];
    }

    /**
     * 检查用户是否有权限查看指定内容
     * @param int $contentId 内容ID
     * @return bool
     */
    public function canViewContent($contentId)
    {
        // 1. 检查用户是否已购买
        if ($this->hasPurchased($contentId)) {
            return true;
        }

        // 2. 检查用户是否为VIP且有权限
        if ($this->isVip()) {
            return true;
        }


        return false;
    }

    /**
     * 检查用户是否购买了指定内容
     * @param int $contentId 内容ID
     * @return bool
     */
    public function hasPurchased($contentId)
    {
        // 查找用户是否有已支付的订单包含该内容
        return $this->orders()
            ->where('goods_id', $contentId)
            ->where('status', 1)
            ->count() > 0;
    }

    /**
     * 记录用户内容查看 todo加载商品详情里
     * @param int $contentId 内容ID
     * @param string $contentType 内容类型
     */
    public function recordContentView($contentId, $contentType = 'chapter')
    {
        // 记录查看历史
        UserViewLog::create([
            'user_id'      => $this->id,
            'content_type' => $contentType,
            'content_id'   => $contentId,
            'view_date'    => date('Y-m-d'),
            'create_time'  => date('Y-m-d H:i:s')
        ]);
    }

    /**
     * 添加积分
     * @param int $points 积分数量
     * @param string $type 积分类型
     * @param string $remark 备注
     * @param int $relationId 关联ID
     * @return bool
     */
    public function addPoints($points, $type, $remark = '', $relationId = 0)
    {
        if ($points <= 0) {
            return false;
        }

        $beforePoints = $this->points;
        $this->points += $points;
        $this->save();

        // 记录积分日志
        UserPointsLog::create([
            'user_id'       => $this->id,
            'points'        => $points,
            'before_points' => $beforePoints,
            'after_points'  => $this->points,
            'type'          => $type,
            'remark'        => $remark,
            'relation_id'   => $relationId,
            'create_time'   => date('Y-m-d H:i:s')
        ]);

        // 更新会员等级
        $this->updateLevel();

        return true;
    }

    /**
     * 扣减积分
     * @param int $points 积分数量
     * @param string $type 积分类型
     * @param string $remark 备注
     * @param int $relationId 关联ID
     * @return bool
     */
    public function reducePoints($points, $type, $remark = '', $relationId = 0)
    {
        if ($points <= 0 || $this->points < $points) {
            return false;
        }

        $beforePoints = $this->points;
        $this->points -= $points;
        $this->save();

        // 记录积分日志
        UserPointsLog::create([
            'user_id'       => $this->id,
            'points'        => -$points,
            'before_points' => $beforePoints,
            'after_points'  => $this->points,
            'type'          => $type,
            'remark'        => $remark,
            'relation_id'   => $relationId,
            'create_time'   => date('Y-m-d H:i:s')
        ]);

        // 更新会员等级
        $this->updateLevel();

        return true;
    }

    /**
     * 更新会员等级
     */
    public function updateLevel()
    {
        // 查找用户积分对应的等级
        $level = UserLevel::where('min_points', '<=', $this->points)
            ->where('max_points', '>=', $this->points)
            ->where('status', 1)
            ->order('min_points', 'desc')
            ->find();

        if ($level && $this->level_id != $level->id) {
            $oldLevelId     = $this->level_id;
            $this->level_id = $level->id;
            $this->save();

            // 发送等级变更通知
            $this->sendLevelChangeNotification($oldLevelId, $level->id);
        }
    }

    /**
     * 发送等级变更通知
     * @param int $oldLevelId 旧等级ID
     * @param int $newLevelId 新等级ID
     */
    protected function sendLevelChangeNotification($oldLevelId, $newLevelId)
    {
        $newLevel = UserLevel::find($newLevelId);
        if (!$newLevel) {
            return;
        }

        // 发送系统通知
        // TODO: 实现系统通知功能
    }

    /**
     * 用户签到
     * @return array
     */
    public function signIn()
    {
        $today = date('Y-m-d');

        // 检查今天是否已签到
        $existSign = UserSignLog::where('user_id', $this->id)
            ->where('sign_date', $today)
            ->find();

        if ($existSign) {
            return [
                'code' => 0,
                'msg'  => '今天已经签到过了'
            ];
        }

        // 查找昨天是否签到，计算连续签到天数
        $yesterday = date('Y-m-d', strtotime('-1 day'));
        $lastSign  = UserSignLog::where('user_id', $this->id)
            ->where('sign_date', $yesterday)
            ->find();

        $continuousDays = 1;
        if ($lastSign) {
            $continuousDays = $lastSign->continuous_days + 1;
            // 超过7天重置为1
            if ($continuousDays > 7) {
                $continuousDays = 1;
            }
        }

        // 计算获得的积分
        $points = $this->calculateSignPoints($continuousDays);

        // 记录签到
        UserSignLog::create([
            'user_id'         => $this->id,
            'continuous_days' => $continuousDays,
            'points'          => $points,
            'sign_date'       => $today,
            'create_time'     => date('Y-m-d H:i:s')
        ]);

        // 增加积分
        $this->addPoints($points, 'sign', '签到奖励');

        return [
            'code' => 1,
            'msg'  => '签到成功',
            'data' => [
                'continuous_days' => $continuousDays,
                'points'          => $points
            ]
        ];
    }

    /**
     * 计算签到积分
     * @param int $continuousDays 连续签到天数
     * @return int
     */
    protected function calculateSignPoints($continuousDays)
    {
        $pointsMap = [
            1 => 5,
            2 => 6,
            3 => 7,
            4 => 8,
            5 => 9,
            6 => 10,
            7 => 15
        ];

        return $pointsMap[$continuousDays] ?? 5;
    }
}
